【小ネタ】AWS Lambda(Python) から Backlog wiki を更新する

【小ネタ】AWS Lambda(Python) から Backlog wiki を更新する

Clock Icon2024.07.10

AWS Lambda 関数から Backlog wiki を更新するための雛形を作ってみました。

AWS上の特定情報を取得してレポートを wiki にダンプするのがモチベーションです。

本ブログでそのコード(Python)と実行例を紹介します。

作ったもの

以下 backlog.pylambda_function.py を含めた Lambda関数(ランタイム: python3.12)を作成しました。

backlog.py
import boto3
import urllib.parse
import urllib.request

ssm = boto3.client('ssm')

def get_api_key(param_name: str) -> str:
    """SSMパラメータストアにあるBacklog APIキー(Secure String)を取得する

    Args:
        param_name (str, optional): APIキーが格納されているパラメータ名.

    Returns:
        str: Backlog API キー
    """
    # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm/client/get_parameter.html
    response = ssm.get_parameter(
        Name=param_name,
        WithDecryption=True
    )
    return response.get('Parameter', {}).get('Value', 'NOVALUE')

def update_wiki_content(space_id: str, wiki_id: str, content: str, api_key: str) -> str:
    """指定した wiki を 指定した content に更新してレスポンスを返す

    Args:
        space_id (str): BacklogのスペースID
        wiki_id (str): 更新対象の wiki_id
        content (str): 更新内容
        api_key (str): Backlog APIキー

    Returns:
        str: レスポンス
    """
    # URLとデータ、ヘッダーを生成する
    url = f"https://{space_id}.backlog.jp/api/v2/wikis/{wiki_id}?apiKey={api_key}"
    data = urllib.parse.urlencode({"content": content}).encode('ascii')
    headers = {"Content-Type": "application/x-www-form-urlencoded"}

    # リクエストを送信して、レスポンスを返す
    # https://docs.python.org/ja/3/howto/urllib2.html#urllib-howto
    # https://developer.nulab.com/ja/docs/backlog/api/2/update-wiki-page/#
    resp = ""
    req = urllib.request.Request(url, data, headers, method='PATCH')
    with urllib.request.urlopen(req) as r:
        resp = r.read().decode()
    return resp
lambda_function.py
import backlog
import os
import datetime
import logging

logger = logging.getLogger()
logger.setLevel("INFO")

def generate_content() -> str:
    """コンテンツを生成する

    Returns:
        str: コンテンツ
    """
    now = datetime.datetime.now().strftime('%Y-%m-%d(%a) %H:%M:%S')
    content = f"""\
# TEST at {now}

XXX
"""
    return content

def lambda_handler(event, context):
    """コンテンツを生成してBacklog wikiを更新する"""
    # 環境変数からBacklog wiki 更新に必要なパラメータを取得する
    wiki_id = os.getenv('wiki_id', default="[WIKI_ID]")
    space_id = os.getenv('space_id', default='[SPACE_ID]')
    ssm_param_name = os.getenv('ssm_param_name', default='[SSM_PARAM_NAME]')
    logger.info(f"wiki_id={wiki_id}, space_id={
                 space_id}, ssm_param_name={ssm_param_name}")

    # コンテンツを生成する
    content = generate_content()
    logger.info(f"content={repr(content[0:50])}...")

    # Backlog wiki を更新する
    resp = backlog.update_wiki_content(
        space_id=space_id,
        wiki_id=wiki_id,
        content=content,
        api_key=backlog.get_api_key(ssm_param_name)
    )
    logger.info(f"resp={repr(resp[0:50])}...")
    return resp

Lambda関数の主な基本設定は以下のとおりです。

設定
ランタイム python3.12
アーキテクチャ arm64
ハンドラー lambda_function.lambda_handler
環境変数 後述
実行ロールの権限 後述

環境変数は以下3つを指定します。

  • wiki_id : 更新先の Backlog wiki の ID
  • space_id : Backlog の スペースID
  • ssm_param_name : Backlog APIキー格納先の SSMパラメータストア名

実行ロールに付与する最小権限は以下2つです。 他必要に応じて権限を付与してください。

CloudWatch Logs にログを流す権限
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:PutLogEvents",
        "logs:CreateLogStream",
        "logs:CreateLogGroup"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:logs:ap-northeast-1:${AccountID}:log-group:/aws/lambda/${FunctionName}:*:*",
        "arn:aws:logs:ap-northeast-1:${AccountID}:log-group:/aws/lambda/${FunctionName}:*"
      ]
    }
  ]
}
SSMパラメータストアからSecureStringを取ってくる権限
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "ssm:GetParameter",
      "Effect": "Allow",
      "Resource": "arn:aws:ssm:ap-northeast-1:${AccountID}:parameter/${ParameterName}"
    },
    {
      "Action": "kms:Decrypt",
      "Effect": "Allow",
      "Resource": "arn:aws:kms:ap-northeast-1:${AccountID}:key/${KMSKeyID}"
    }
  ]
}

使ってみる

作成した Lambda 関数 (以降 update-backlog-wiki )を実行してみます。

$ aws lambda invoke --function-name update-backlog-wiki /dev/stdout
"{\"id\":1111111111,\"projectId\":1010101010,\"name\":\"Kawahara/sandbox\",\"content\":\"# TEST at 2024-07-10(Wed) 00:17:57\\n\\nXXX\\n\",...以下略
StatusCode: 200

実行後 wiki が更新されていることを確認できました。

sc_2024-07-10_09-21-22_12907

おわりに

「Backlog wiki を更新 Lambda関数」の雛形を作成してみました。

今回はオンデマンドの実行でしたが、自動トリガーも可能です。 EventBridge や SNS あたりとうまく連携していきましょう。

以上、参考になれば幸いです。

参考

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.